package conference.view;

import org.gstreamer.Element;
import org.gstreamer.ElementFactory;
import org.gstreamer.Pipeline;
import org.gstreamer.State;
import org.gstreamer.StateChangeReturn;
import org.gstreamer.swing.VideoComponent;

/**
*
* a class to receive the audio and video UDP streams
* 
*/
public class RecieverStreamUDP {
	
	private final int DEFAULTVIDEOINPORT = 6968;
	private final int DEFAULTAUDIOINPORT = 6969;
	
	private Pipeline videoRecieverPipeline;
	private Element videoSrc;
	private Element videoDec;
	private Element videoColorSpace;
	private Element videoSink;
	
	private Pipeline audioRecieverPipeline;
	private Element audioSrc;
	private Element audioDec;
	private Element audioConvert;
	private Element audioSink;
	
	public RecieverStreamUDP(VideoComponent videoComponent){
		
		// Creation of the videoRecieverPipeline elements :
		videoSrc = ElementFactory.make("udpsrc","VideoSrc");
		videoSrc.set("port", DEFAULTVIDEOINPORT);
		videoDec = ElementFactory.make("theoradec","VideoDec"); // we could use theoradec instead of decodebin
		videoColorSpace = ElementFactory.make("ffmpegcolorspace","VideoColorSpace");
		videoSink = videoComponent.getElement();
		// Creation of the videoRecieverPipeline pipeline and linking of the elements :
		videoRecieverPipeline = new Pipeline("AudioRecieverPipeline");
		videoRecieverPipeline.addMany(videoSrc, videoDec, videoColorSpace, videoSink);
		videoSrc.link(videoDec);
		videoDec.link(videoColorSpace);
		videoColorSpace.link(videoSink);
		
		// Creation of the audioRecieverPipeline elements :
		audioSrc = ElementFactory.make("udpsrc","AudioSrc");
		audioSrc.set("port", DEFAULTAUDIOINPORT);
		audioDec = ElementFactory.make("vorbisdec","AudioDec");
		audioConvert = ElementFactory.make("audioconvert","AudioConvert");
		audioSink = ElementFactory.make("autoaudiosink", "AudioSink");
		// Creation of the audioRecieverPipeline pipeline and linking of the elements :
		audioRecieverPipeline = new Pipeline("AudioRecieverPipeline");
		audioRecieverPipeline.addMany(audioSrc, audioDec, audioConvert, audioSink);
		audioSrc.link(audioDec);
		audioDec.link(audioConvert);
		audioConvert.link(audioSink);
		
		startPipelines();
	}
	
	public RecieverStreamUDP(VideoComponent videoComponent, int videoInPort, int audioInPort){
		// Creation of the videoRecieverPipeline elements :
		videoSrc = ElementFactory.make("udpsrc","VideoSrc");
		videoSrc.set("port", videoInPort);
		videoDec = ElementFactory.make("theoradec","VideoDec");
		videoColorSpace = ElementFactory.make("ffmpegcolorspace","VideoColorSpace");
		videoSink = videoComponent.getElement();
		// Creation of the videoRecieverPipeline pipeline and linking of the elements :
		videoRecieverPipeline = new Pipeline("AudioRecieverPipeline");
		videoRecieverPipeline.addMany(videoSrc, videoDec, videoColorSpace, videoSink);
		videoSrc.link(videoDec);
		videoDec.link(videoColorSpace);
		videoColorSpace.link(videoSink);
		
		// Creation of the audioRecieverPipeline elements :
		audioSrc = ElementFactory.make("udpsrc","AudioSrc");
		audioSrc.set("port", audioInPort);
		audioDec = ElementFactory.make("vorbisdec","AudioDec");
		audioConvert = ElementFactory.make("audioconvert","AudioConvert");
		audioSink = ElementFactory.make("autoaudiosink", "AudioSink");
		// Creation of the audioRecieverPipeline pipeline and linking of the elements :
		audioRecieverPipeline = new Pipeline("AudioRecieverPipeline");
		audioRecieverPipeline.addMany(audioSrc, audioDec, audioConvert, audioSink);
		audioSrc.link(audioDec);
		audioDec.link(audioConvert);
		audioConvert.link(audioSink);
		
		startPipelines();
	}
	
	/**
	* starts the audio pipeline and the video pipeline of the ReceiverStreamUDP
	*  
	*/
	public void startPipelines() {
		StateChangeReturn videoStartResult = videoRecieverPipeline.setState(State.PLAYING);
		StateChangeReturn audioStartResult = audioRecieverPipeline.setState(State.PLAYING);
		System.out.println("RecieverStreamUDP: Pipelines starting... video "+videoStartResult+" on port "+videoSrc.get("port")+" - audio "+audioStartResult+" on port "+audioSrc.get("port"));
	}
	
	/**
	* stops the audio pipeline and the video pipeline of the ReceiverStreamUDP
	*  
	*/
	public void stopPipelines() {
		StateChangeReturn videoStopResult = videoRecieverPipeline.setState(State.NULL);
		StateChangeReturn audioStopResult = audioRecieverPipeline.setState(State.NULL);
		System.out.println("RecieverStreamUDP: Pipeline stopping... video ok "+videoStopResult+" - audio "+audioStopResult);
	}
	
	/**
	* stops and starts the audio pipeline and the video pipeline of the ReceiverStreamUDP
	*  
	*/
	public void restartPipelines(){
		stopPipelines();
		startPipelines();
	}

	/**
	* set the port of the UDP source for the video
	*  
	*  @param port the new video UDP port
	*/
	public void setVideoInPort(int port) {
		stopPipelines();
		videoSrc.set("port", port);
		startPipelines();
	}
	
	/**
	* set the port of the UDP source for the audio
	*  
	*  @param port the new audio UDP port
	*/	
	public void setAudioInPort(int port){
		stopPipelines();
		audioSrc.set("port", port);
		startPipelines();
	}
	
	/**
	* set the ports of the UDP sources for the video and audio
	*  
	*  @param videoPort the new video UDP port
	*  @param audioPort the new audio UDP port
	*/
	public void setInputPorts(int videoPort, int audioPort){
		stopPipelines();
		videoSrc.set("port", videoPort);
		audioSrc.set("port", audioPort);
		startPipelines();
	}
	
	/**
	* returns true if the video pipeline is playing
	*  
	*  @return true if the video pipeline state is PLAYING, false otherwise
	*/
	public boolean isVideoPlaying(){
		boolean result = false;
		try{
			result = this.videoRecieverPipeline.getState().equals(State.PLAYING);
		}catch(Exception e){
			System.out.println("RevieverStreamUDP : Exception when trying to get the state of the videoRecieverPipeline !");
		}
		return result;
	}
	
	/**
	* returns true if the audio pipeline is playing
	*  
	*  @return true if the audio pipeline state is PLAYING, false otherwise
	*/
	public boolean isAudioPlaying(){
		boolean result = false;
		try{
			result = this.audioRecieverPipeline.getState().equals(State.PLAYING);
		}catch(Exception e){
			System.out.println("RevieverStreamUDP : Exception when trying to get the state of the audioRecieverPipeline !");
		}
		return result;
	}
}
